;; Data Module
;;;;;;;;;;;;;;;;;;;;;;;
;; Defines a Data Structur based on an NSArrayController, which can be used p.e. as Array, Dictionary.
;; main reason is that we can connect this to an NSTableview

(define kR:data:temp 0)
(define kR:data:temp-dict 0)

(define kR:data
   (lambda ()
      (set! kR:data:temp (objc:make "NSArrayController" "init"))
      (objc:call kR:data:temp "setContent:" (objc:call "NSMutableArray" "array"))
      kR:data:temp))

(define kR:data:add
   (lambda (data to-add)
      (objc:call data "addObject:"
          
          (objc:list->nsdictionary 
              (map (lambda (entry)
                    ;We automatically convert lists in the value
                    ; to kR:data's
                    (if (list? (cdr entry))
                        (cons (car entry) (kR:data:add-many (kR:data) (cdr entry)))
                        entry))
              to-add)))
      data))

(define kR:data:add-many
   (lambda (data to-add)
      (for-each 
                 (lambda (add-me)
                    (kR:data:add data add-me))
                 to-add)
      data))
                  
(define kR:data:set-filter
   (lambda (data filter)
      (objc:call data "setFilterPredicate:" 
           (objc:call "NSPredicate" "predicateWithFormat:" filter))
      data))

(define kR:data:remove-filter
   (lambda (data)
      (objc:call data "setFilterPredicate:" 0)
      data))

(define kR:data:remove-at-index
   (lambda (data index)
      (objc:call data "removeObjectAtArrangedObjectIndex:" index)
      data))

(define kR:data:remove-selected
   (lambda (data)
      (objc:call data "removeObjects:" (objc:call data "selectedObjects"))
      data))

(define kR:data:count
   (lambda (data)
      (objc:nsnumber->number (objc:call (objc:call data "content") "count"))))

(define kR:data:select
   (lambda (data index)
      (objc:call data "setSelectionIndex:" index)
      data))

(define kR:data:reset
   (lambda (data)
        (objc:call data "removeObjects:" (objc:call data "content"))))  

(define kR:data:select-next
   (lambda (data)
      (objc:call data "selectNext:")
      data))

(define kR:data:select-prev
   (lambda (data)
      (objc:call data "selectPrevious:")
      data))

(define kR:data:selected
   (lambda (data)
      (objc:call (objc:call data "selectedObjects") "lastObject")))

(define kR:data:selected->list
   (lambda (data)
      (objc:nsdictionary->list (kR:data:selected data))))

(define kR:data:set-for-selected
   (lambda (data key value)
      (objc:set-value-for-key 
           (objc:call (objc:call data "selectedObjects") "objectAtIndex:" 0) 
           key value)
      data))

(define kR:data:get-for-selected
   (lambda (data key)
      (objc:get-value-for-key
         (objc:call (objc:call data "selectedObjects") "objectAtIndex:" 0)
         key)))
(define kR:data->list:temp 0)
(define kR:data->list
   ;generates a nested list of all those entries
   (lambda (data . non-recursive)
      (map (lambda (data-entry)
             ;We have two nested Lists:
             ; the data list hich contains the data-entries
             ; the data-entry for itself is also a list, which contains
             ; one or more (cons) structures
             ;Therefore: iter threw all children 
             (map (lambda (dict-entry)
                  ;if the value of a dict entry
                  ; is a objc object
                  ; we assume it as a NSArrayController or kR:data object
                  ; therefore we recurse to get its contents for its parent
                  ;AND do we want recursive (performance) (default
                  (if (and (objc? (cdr dict-entry)) (= (length non-recursive) 0))
                      (cons (car dict-entry) (kR:data->list (cdr dict-entry)))                          
                      dict-entry))
                  data-entry))
           (objc:nsarray->list (objc:call data "arrangedObjects")))))

(define kR:list->data
   (lambda (mylist)
      (kR:data:add-many (kR:data) mylist)))
                 
(define kR:data:save-to-file 
   (lambda (data filename)
      (with-output-to-file filename
          (lambda () (write (kR:data->list data))))))
                 
(define kR:data:load-from-file 
   (lambda (filename)
      (with-input-from-file filename
           (lambda ()
               (kR:data:add-many (kR:data) (read))))))


(define kR:data:observer:bundle 
   (objc:call "NSBundle" "bundleWithPath:" (kR:pathTo "utils/observer.framework")))
(objc:call kR:data:observer:bundle "load")

(define kR:data:observe:temp 0)

(define kR:data:observer
   (lambda (data context)
      (objc:make "kRNSArrayControllerObserver" "initWithBridge:controller:context:" *impromptu-objc-bridge* data (objc:number->nsnumber context))))

(define kR:data:observe-selection
   (lambda (data context)
      (set! kR:data:observe:temp (kR:data:observer data context))
      (objc:call kR:data:observe:temp "observeSelection"))
      kR:data:observe:temp)

(define kR:data:observe-content
   (lambda (data context)
      (set! kR:data:observe:temp (kR:data:observer data context))
      (objc:call kR:data:observe:temp "observeContent"))
      kR:data:observe:temp)

(define kR:data:observe-key
   (lambda (data context key)
      (set! kR:data:observe:temp (kR:data:observer data context))
      (objc:call kR:data:observe:temp "observeKey:" key))
      kR:data:observe:temp)